package satir.framework;

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.DataInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileWriter;
import java.io.InputStreamReader;
import org.json.JSONException;
import org.json.JSONObject;

/**
 * The Class JSONIOPerformer.
 * @version 3.0 April 2012
 * @author Creative Family
 */
public class JSONIOPerformer {

    /** The json object. */
    private JSONObject jsonObject;

    /** The filename. */
    private String filename;

    /**
     * Instantiates a new jSONIO performer.
     * @param filename
     *            the filename
     * @param isCreateIfNotFound
     *            the is create if not found
     * @throws JSONIOPerformerJSONDecodeException
     *             the JSON decode fail exception
     * @throws JSONIOPerformerReadException
     *             the read fail exception
     */
    public JSONIOPerformer(final String filename, final boolean isCreateIfNotFound)
	    throws JSONIOPerformerJSONDecodeException,
	    JSONIOPerformerReadException {
	this.filename = filename;
	try {
	    jsonObject = new JSONObject(read());
	} catch (JSONIOPerformerReadException e) {
	    if (isCreateIfNotFound) {
		jsonObject = new JSONObject();
	    } else {
		throw e;
	    }
	} catch (JSONException e) {
	    throw new JSONIOPerformerJSONDecodeException(filename);
	}
    }

    /**
     * Instantiates a new jSONIO performer.
     * @param filename
     *            the filename
     * @throws JSONIOPerformerReadException
     *             the jSONIO performer read exception
     * @throws JSONIOPerformerJSONDecodeException
     *             the jSONIO performer json decode exception
     */
    public JSONIOPerformer(final String filename)
	    throws JSONIOPerformerReadException,
	    JSONIOPerformerJSONDecodeException {
	this(filename, false);
    }

    /**
     * Retrieve the JSON object.
     * @return the jSON object
     */
    public JSONObject retrieve() {
	return jsonObject;
    }

    /**
     * Return the JSON object detail.
     * @return the detail of JSON object
     */
    public String toString() {
	return jsonObject.toString();
    }

    /**
     * Write.
     * @throws JSONIOPerformerWriteException
     *             the jSONIO performer write exception
     */
    public void write() throws JSONIOPerformerWriteException {
	FileWriter fstream;
	BufferedWriter out;
	try {
	    fstream = new FileWriter(filename);
	    out = new BufferedWriter(fstream);
	    out.write(jsonObject.toString());
	    out.close();
	    fstream.close();
	} catch (Exception e) {
	    e.printStackTrace();
	    // throw new JSONIOPerformerWriteException(filename);
	}
    }

    /**
     * Read the filename.
     * @return the string
     * @throws JSONIOPerformerReadException
     *             the jSONIO performer read exception
     */
    private String read() throws JSONIOPerformerReadException {
	/*
	 * StringBuilder cardTxt = new StringBuilder(); try { InputStreamReader
	 * inS = new InputStreamReader(
	 * ClassLoader.getSystemResourceAsStream(filename)); BufferedReader
	 * input = new BufferedReader(inS); String line; while ((line =
	 * input.readLine()) != null) { cardTxt.append(line.trim()); } } catch
	 * (Exception e) { throw new JSONIOPerformerReadException(filename); }
	 * return cardTxt.toString();
	 */

	// New
	String content = "";
	try {
	    // Open the file that is the first
	    // command line parameter
	    FileInputStream fstream = new FileInputStream(filename);
	    // Get the object of DataInputStream
	    DataInputStream in = new DataInputStream(fstream);
	    BufferedReader br = new BufferedReader(new InputStreamReader(in));
	    StringBuffer sb = new StringBuffer();
	    String strLine;
	    // Read File Line By Line
	    while ((strLine = br.readLine()) != null) {
		// Print the content on the console
		sb.append(strLine);
	    }
	    // Close the input stream
	    in.close();
	    content = sb.toString();
	} catch (Exception e) { // Catch exception if any
	    throw new JSONIOPerformerReadException(e.getMessage());
	}
	return content;
    }

    /**
     * The Class JSONIOPerformerException.
     */
    public class JSONIOPerformerException extends Exception {

	/**
	 * Instantiates a new jSONIO performer exception.
	 * @param message
	 *            the message
	 */
	public JSONIOPerformerException(final String message) {
	    super(message);
	}
    }

    /**
     * The Class JSONIOPerformerReadException.
     */
    public class JSONIOPerformerReadException extends JSONIOPerformerException {

	/**
	 * Instantiates a new jSONIO performer read exception.
	 * @param filename
	 *            the filename
	 */
	public JSONIOPerformerReadException(final String filename) {
	    super("ERROR: Perform read file failure! Reference: filename["
		    + filename + "], currentLocation["
		    + new File(".").getAbsolutePath() + "]");
	}
    }

    /**
     * The Class JSONIOPerformerWriteException.
     */
    public class JSONIOPerformerWriteException extends JSONIOPerformerException {

	/**
	 * Instantiates a new jSONIO performer write exception.
	 * @param filename
	 *            the filename
	 */
	public JSONIOPerformerWriteException(final String filename) {
	    super("ERROR: Perform write file failure! Reference: filename["
		    + filename + "]");
	}
    }

    /**
     * The Class JSONIOPerformerJSONDecodeException.
     */
    public class JSONIOPerformerJSONDecodeException extends
	    JSONIOPerformerException {

	/**
	 * Instantiates a new jSONIO performer json decode exception.
	 * @param filename
	 *            the filename
	 */
	public JSONIOPerformerJSONDecodeException(final String filename) {
	    super(
		    "ERROR: The target file is not a JSON structure! Reference: filename["
			    + filename + "]");
	}
    }
}
